package com.xudm.cdg.service;

import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;
import java.util.Optional;

/**
 * minio操作接口
 *
 * @author xudm
 */
@Component
public interface MinioService {

    /******************************  Operate Bucket Start  ******************************/

    /**
     * 创建桶
     *
     * @param bucketName 桶名
     */
    void createBucket(String bucketName);

    /**
     * 判断桶是否存在
     *
     * @param bucketName 桶名
     * @return boolean
     */
    boolean bucketExists(String bucketName);


    /**
     * 获取桶策略
     *
     * @param bucketName 桶名
     * @return String
     */
    String getBucketPolicy(String bucketName);


    /**
     * 获取所有桶
     *
     * @return List<Bucket>
     */
    List<Bucket> getAllBuckets();

    //根据桶名获取其相关信息

    /**
     * 根据桶名获取其相关信息
     *
     * @param bucketName 桶名
     * @return Optional<Bucket>
     */
    Optional<Bucket> getBucket(String bucketName);

    /**
     * 删除桶，需桶中不含有文件
     *
     * @param bucketName 桶名
     */
    void removeBucket(String bucketName);

    /******************************  Operate Bucket End  ******************************/

    /******************************  Operate Files Start  ******************************/


    /**
     * 判断文件夹是否存在（获取默认桶内文件）
     *
     * @param filePath 文件路径
     * @return boolean
     */
    boolean isFolderExist(String filePath);


    /**
     * 判断桶内文件夹是否存在
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    boolean isFolderExist(String bucketName, String filePath);


    /**
     * 创建文件夹或目录，如果文件夹或目录存在不报错也不会覆盖
     *
     * @param bucketName 桶名
     * @param dirPath    文件路径
     * @return
     */
    ObjectWriteResponse createDir(String bucketName, String dirPath);

    /**
     * 判断文件是否存在（获取默认桶内文件）
     *
     * @param filePath 文件路径
     * @return
     */
    boolean isObjectExist(String filePath);


    /**
     * 判断桶内文件是否存在
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    boolean isObjectExist(String bucketName, String filePath);


    /**
     * 根据文件前置查询文件，是否采用递归（获取默认桶内文件）
     *
     * @param prefix    文件前缀
     * @param recursive 是否递归
     * @return
     */
    List<Item> getAllObjectsByPrefix(String prefix, boolean recursive);


    /**
     * 根据桶内文件前置查询文件，是否采用递归
     *
     * @param bucketName 桶名
     * @param prefix     文件前缀
     * @param recursive  是否递归
     * @return
     */
    List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive);


    /**
     * 获取文件流（获取默认桶内文件）
     *
     * @param filePath 文件路径
     * @return
     */
    InputStream getObject(String filePath);

    /**
     * 获取桶内文件流
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    InputStream getObject(String bucketName, String filePath);


    /**
     * 断点下载（获取默认桶内文件）
     *
     * @param filePath 文件路径
     * @param offset   偏移量
     * @param length   长度
     * @return
     */
    InputStream getObject(String filePath, long offset, long length);


    /**
     * 桶内断点下载
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @param offset     偏移量
     * @param length     长度
     * @return
     */
    InputStream getObject(String bucketName, String filePath, long offset, long length);


    /**
     * 获取路径下文件列表获取默认桶内文件）
     *
     * @param prefix    文件前缀
     * @param recursive 是否递归
     * @return
     */
    Iterable<Result<Item>> listObjects(String prefix, boolean recursive);

    /**
     * 获取桶内路径下文件列表
     *
     * @param bucketName 桶名
     * @param prefix     文件前缀
     * @param recursive  是否递归
     * @return
     */
    Iterable<Result<Item>> listObjects(String bucketName, String prefix, boolean recursive);


    /**
     * 使用MultipartFile进行文件上传（默认桶）
     *
     * @param file     文件
     * @param filePath 文件路径
     * @return
     */
    ObjectWriteResponse uploadFile(MultipartFile file, String filePath);

    /**
     * 使用MultipartFile进行文件上传
     *
     * @param bucketName 桶名
     * @param file       文件
     * @param filePath   文件路径
     * @return
     */
    ObjectWriteResponse uploadFile(String bucketName, MultipartFile file, String filePath);

    /**
     * 上传本地文件到默认桶
     *
     * @param filePath      文件路径
     * @param localFilePath 本地文件路径
     * @return
     */
    ObjectWriteResponse uploadFile(String filePath, String localFilePath);

    /**
     * 上传本地文件到指定桶
     *
     * @param bucketName    桶名
     * @param filePath      文件路径
     * @param localFilePath 本地文件路径
     * @return
     */
    ObjectWriteResponse uploadFile(String bucketName, String filePath, String localFilePath);

    /**
     * 通过流上传文件到默认桶
     *
     * @param filePath    文件路径
     * @param inputStream 输入流
     * @return
     */
    ObjectWriteResponse uploadFile(String filePath, InputStream inputStream);

    /**
     * 通过流上传文件到指定桶
     *
     * @param bucketName  桶名
     * @param filePath    文件路径
     * @param inputStream 输入流
     * @return
     */
    ObjectWriteResponse uploadFile(String bucketName, String filePath, InputStream inputStream);

    /**
     * 获取文件信息, 如果抛出异常则说明文件不存在（默认桶）
     *
     * @param filePath 文件路径
     * @return
     */
    StatObjectResponse getFileStatusInfo(String filePath);

    /**
     * 获取文件信息, 如果抛出异常则说明文件不存在
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    StatObjectResponse getFileStatusInfo(String bucketName, String filePath);


    /**
     * 拷贝文件，选择覆盖时如果目标路径下有同名文件会被覆盖，小心操作！
     *
     * @param bucketName       桶名
     * @param filePath         文件路径
     * @param targetBucketName 目标桶名
     * @param targetFilePath   目标文件路径
     * @param isCover          是否覆盖
     * @return
     */
    boolean copyFile(String bucketName, String filePath, String targetBucketName, String targetFilePath, boolean isCover);

    /**
     * 移动文件，选择覆盖时如果目标路径下有同名文件会被覆盖，小心操作！
     *
     * @param bucketName       桶名
     * @param filePath         文件路径
     * @param targetBucketName 目标桶名
     * @param targetFilePath   目标文件路径
     * @param isCover          是否覆盖
     * @return
     */
    boolean moveFile(String bucketName, String filePath, String targetBucketName, String targetFilePath, boolean isCover);

    /**
     * 重命名文件,默认名称冲突覆盖。
     *
     * @param bucketName  桶名
     * @param filePath    文件路径
     * @param newFileName 新文件名
     * @return
     */
    boolean renameFile(String bucketName, String filePath, String newFileName);

    /**
     * 重命名文件,默认名称选择冲突覆盖。
     *
     * @param bucketName  桶名
     * @param filePath    文件路径
     * @param newFileName 新文件名
     * @param isCover     是否覆盖
     * @return
     */
    boolean renameFile(String bucketName, String filePath, String newFileName, boolean isCover);


    /**
     * 删除文件或文件夹。（默认桶）
     *
     * @param filePath 文件路径
     * @return
     */
    boolean removeFile(String filePath);

    /**
     * 删除文件或文件夹。
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    boolean removeFile(String bucketName, String filePath);

    /**
     * 批量删除文件或文件夹。（默认桶）
     *
     * @param filepaths 文件路径
     * @return
     */
    boolean removeFiles(List<String> filepaths);

    /**
     * 批量删除文件或文件夹。
     *
     * @param bucketName 桶名
     * @param filepaths  文件路径
     * @return
     */
    boolean removeFiles(String bucketName, List<String> filepaths);

    /**
     * 获取文件外链
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    String getPresignedObjectUrl(String bucketName, String filePath);

    /**
     * 获取文件外链
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @param expires    过期时间
     * @return
     */
    String getPresignedObjectUrl(String bucketName, String filePath, Integer expires);

    /******************************  Operate Files End  ******************************/

    /******************************  Operate Other Start  ******************************/

    /**
     * 根据URL获取桶名
     *
     * @param url URL
     * @return
     */
    String getBucketNameByURL(String url);

    /**
     * 根据URL获取文件名
     *
     * @param url URL
     * @return
     */
    String getFileNameByURL(String url);

    /**
     * 根据URL获取文件路径
     *
     * @param url URL
     * @return
     */
    String getFilePathByURL(String url);

    /**
     * 根据文件路径获取完整文件名
     *
     * @param filePath 文件路径
     * @return
     */
    String getFullFileNameByURL(String filePath);

    /**
     * 根据存储地址获取完整桶存储路径（获取默认桶）
     *
     * @param filePath 文件路径
     * @return
     */
    String getUploadPath(String filePath);


    /**
     * 根据桶和存储地址获取完整桶存储路径
     *
     * @param bucketName 桶名
     * @param filePath   文件路径
     * @return
     */
    String getUploadPath(String bucketName, String filePath);


    /******************************  Operate Other End  ******************************/
}
